 package com.jpxx.netty.runtime;

import java.util.concurrent.TimeUnit;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;

public class Client {  

	//实例化  Client客户端
	private static class SingletonHolder{
		static final Client instance = new Client();
	}
	public static Client getInstance(){
		return SingletonHolder.instance;//匿名内部类
	}

	private EventLoopGroup group;
	private Bootstrap b;
	private ChannelFuture cf;
	
	private Client(){
		group =  new NioEventLoopGroup();
		b =  new Bootstrap();
		b.group(group)  
		.channel(NioSocketChannel.class)  
		//.handler(new LoggingHandler(LogLevel.INFO))//日志
		.handler(new ChannelInitializer<SocketChannel>() {  
			@Override  
			public void initChannel(SocketChannel sc) throws Exception {  
				 sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());  
	             sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
	             //超时Handler 当服务器端与客户端超过规定的5分钟内没有进行通信，则会关闭相应的通到，节约资源
	             sc.pipeline().addLast(new ReadTimeoutHandler(5));//读写超过5秒 没有发送数据，就断开连接
	             sc.pipeline().addLast(new ClientHandler());
			}  
		});  
	}
	public void connect (){
		 try {
			this.cf = b.connect("127.0.0.1",8765).sync();
			System.out.println("远程服务器已经连接，你（客户端）可以进行数据交换``");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	
	
	public ChannelFuture getChannelFuture(){
		if(this.cf ==null) {
			this.connect();	//通到是空 连接
		}
		
		if(!this.cf.channel().isActive()) {
			this.connect();//通道未激活  就连接
		}
		return this.cf;
	}
	
	
	
	
	public static void main(String[] args) throws Exception {
	 
			final Client c = Client.getInstance();//封装的实例化
			
			ChannelFuture cf = c.getChannelFuture();
			
			for (int i = 1; i <= 3; i++) {
				Request request = new Request();
				request.setId("id:"+i);
				request.setName("pro"+i);
				request.setRequestMessage(" "+i);
				cf.channel().writeAndFlush(request);
				TimeUnit.SECONDS.sleep(2);//休息4秒
			}
			
			cf.channel().closeFuture().sync();//阻塞
			
			//新建一个线程
//			new Thread(new Runnable(){
//				@Override
//				public void run() {
//					try {
//						System.out.println("--------------------------------");
//						System.out.println("进入子线程——再次给客户端发送数据");
//						ChannelFuture cf = c.getChannelFuture();//再次建立连接
//						//System.out.println(cf.channel().isActive());
//						//System.out.println(cf.channel().isOpen());
//						//再次发送数据
//						Request request = new Request();
//						request.setId("id:"+4);
//						request.setName("pro"+4);
//						request.setRequestMessage("子线程"+4);
//						cf.channel().writeAndFlush(request);
//						
//						cf.channel().closeFuture().sync();
//						
//						System.out.println("子线程结束了");
//					} catch (Exception e) {
//						// TODO Auto-generated catch block
//						e.printStackTrace();
//					}
//					
//				}
//				
//			}).start();//启动线程
			System.out.println("断开连接，Client主线程结束了");
	}
}  